package com.time.admin.domain.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.time.admin.common.entity.PageResult;
import com.time.admin.common.enums.AuditStatusEnum;
import com.time.admin.common.enums.IsActiveStatusEnum;
import com.time.admin.common.enums.IsDeletedFlagEnum;
import com.time.admin.domain.constants.ExceptionCode;
import com.time.admin.domain.converter.FriendLinkBOConverter;
import com.time.admin.domain.entity.FriendLinkBO;
import com.time.admin.domain.exception.AlreadyExistsException;
import com.time.admin.domain.redis.RedisUtil;
import com.time.admin.domain.service.AdminFriendLinkDomainService;
import com.time.admin.infra.basic.entity.FriendLink;
import com.time.admin.infra.basic.service.FriendLinkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * 友链管理领域服务层实现类
 *
 * @author: HuangQi
 * @date: Created in 16:15 2025/10/31
 * @description: 友链管理领域服务层实现类
 */
@Slf4j
@Service("adminFriendLinkDomainService")
public class AdminFriendLinkDomainServiceImpl implements AdminFriendLinkDomainService {

    @Autowired
    private FriendLinkService friendLinkService;

    @Autowired
    private RedisUtil redisUtil;

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private static final long FRIEND_LINK_CACHE_TIMEOUT_MINUTES = 12L;
    private static final long FRIEND_LINK_CACHE_JITTER_MINUTES = 5L;
    private static final TimeUnit FRIEND_LINK_CACHE_TIMEUNIT = TimeUnit.MINUTES;
    private static final long DASHBOARD_CACHE_TIMEOUT_MINUTES = 3L;
    private static final long DASHBOARD_CACHE_JITTER_MINUTES = 2L;

    @Override
    public Boolean add(FriendLinkBO friendLinkBO) {
        if (log.isInfoEnabled()) {
            log.info("AdminFriendLinkDomainServiceImpl.add.bo:{}", friendLinkBO);
        }

        // 参数转换
        FriendLink friendLink = FriendLinkBOConverter.INSTANCE.convertBOToEntity(friendLinkBO);
        friendLink.setStatus(IsActiveStatusEnum.ACTIVE.getCode());
        friendLink.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        friendLink.setAuditStatus(AuditStatusEnum.UN_KOWN.getCode());

        // 检查当前标签的名称是否已经存在
        if (isExistTag(friendLink.getLinkName())) {
            throw new AlreadyExistsException(ExceptionCode.FRIENDLINK_ALREADY_EXISTS, "该友链名称已经存在");
        }

        // 调用 service
        int count = friendLinkService.insert(friendLink);

        return count > 0;
    }

    /**
     * 检查友链名称是否已经存在
     *
     * @param linkName 友链名称
     * @return 是否存在，true-存在，false-不存在
     */
    private boolean isExistTag(String linkName) {
        FriendLink friendLink = friendLinkService.queryByLinkName(linkName);
        return !Objects.isNull(friendLink);
    }

    @Override
    public Boolean update(FriendLinkBO friendLinkBO) {
        if (log.isInfoEnabled()) {
            log.info("AdminFriendLinkDomainServiceImpl.update.bo:{}", friendLinkBO);
        }

        // 参数转换
        FriendLink friendLink = FriendLinkBOConverter.INSTANCE.convertBOToEntity(friendLinkBO);

        // 调用 service
        int count = friendLinkService.update(friendLink);

        return count > 0;
    }

    @Override
    public Boolean delete(Long id) {
        if (log.isInfoEnabled()) {
            log.info("AdminFriendLinkDomainServiceImpl.delete.id:{}", id);
        }

        // 参数转换
        FriendLink friendLink = new FriendLink();
        friendLink.setLinkId(id);
        friendLink.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());

        // 调用 service
        int count = friendLinkService.update(friendLink);

        return count > 0;
    }

    @Override
    public PageResult<FriendLinkBO> queryAllFriendLink(FriendLinkBO friendLinkBO) {
        if (log.isInfoEnabled()) {
            log.info("AdminTagDomainServiceImpl.queryAllFriendLink.bo:{}", friendLinkBO);
        }

        String cacheKey = redisUtil.buildKey("admin", "friendLink", "queryAll", serializeKey(friendLinkBO));
        PageResult<FriendLinkBO> cacheResult = getCache(cacheKey, new TypeReference<PageResult<FriendLinkBO>>() {});
        if (cacheResult != null) {
            return cacheResult;
        }

        // 参数转换
        FriendLink friendLink = FriendLinkBOConverter.INSTANCE.convertBOToEntity(friendLinkBO);
        friendLink.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());

        // 创建分页结果
        PageResult<FriendLinkBO> pageResult = new PageResult<>();
        pageResult.setPageNo(friendLinkBO.getPageNo());
        pageResult.setPageSize(friendLinkBO.getPageSize());

        // 获取总记录数
        int total = friendLinkService.countAll();

        // 获取分页的标签信息
        int start = (pageResult.getPageNo() - 1) * pageResult.getPageSize();
        List<FriendLink> friendLinkList = friendLinkService.queryPage(friendLink, start, pageResult.getPageSize());

        // 参数转换
        List<FriendLinkBO> friendLinkBOList = FriendLinkBOConverter.INSTANCE.convertEntityListToBO(friendLinkList);

        // 构建分页结果
        pageResult.setTotal(total);
        pageResult.setResult(friendLinkBOList);

        setCache(cacheKey, pageResult, FRIEND_LINK_CACHE_TIMEOUT_MINUTES, FRIEND_LINK_CACHE_JITTER_MINUTES);
        // 返回结果
        return pageResult;
    }

    @Override
    public FriendLinkBO queryLinkDashboard() {
        if (log.isInfoEnabled()) {
            log.info("AdminTagDomainServiceImpl.queryLinkDashboard");
        }

        String cacheKey = redisUtil.buildKey("admin", "friendLink", "dashboard");
        FriendLinkBO cacheResult = getCache(cacheKey, new TypeReference<FriendLinkBO>() {});
        if (cacheResult != null) {
            return cacheResult;
        }

        // 获取友链总数
        int totalLinks = friendLinkService.countAll();
        // 活跃友链数
        int activeLinks = friendLinkService.countByAuditStatus(IsActiveStatusEnum.ACTIVE.getCode());
        // 获取待审核友链数
        int pendingLinks = friendLinkService.countByAuditStatus(AuditStatusEnum.PENDING.getCode());
        // 获取申请未通过友链总数
        int totalAuditLinks = totalLinks - friendLinkService.countByAuditStatus(AuditStatusEnum.UN_KOWN.getCode());
        // 构建返回值
        FriendLinkBO friendLinkBO = new FriendLinkBO();
        friendLinkBO.setTotalLinks(totalLinks);
        friendLinkBO.setActiveLinks(activeLinks);
        friendLinkBO.setPendingLinks(pendingLinks);
        friendLinkBO.setTotalAuditLinks(totalAuditLinks);

        setCache(cacheKey, friendLinkBO, DASHBOARD_CACHE_TIMEOUT_MINUTES, DASHBOARD_CACHE_JITTER_MINUTES);
        return friendLinkBO;
    }

    private <T> T getCache(String key, TypeReference<T> typeReference) {
        try {
            String cacheValue = redisUtil.get(key);
            if (cacheValue == null) {
                return null;
            }
            return OBJECT_MAPPER.readValue(cacheValue,
                    OBJECT_MAPPER.getTypeFactory().constructType(typeReference.getType()));
        } catch (Exception e) {
            log.warn("AdminFriendLinkDomainServiceImpl.getCache.error:key={}, msg={}", key, e.getMessage());
            return null;
        }
    }

    private void setCache(String key, Object value, long ttlMinutes, long jitterMinutes) {
        try {
            long ttl = ttlMinutes + ThreadLocalRandom.current().nextLong(jitterMinutes + 1);
            redisUtil.set(key, OBJECT_MAPPER.writeValueAsString(value), ttl, FRIEND_LINK_CACHE_TIMEUNIT);
        } catch (Exception e) {
            log.warn("AdminFriendLinkDomainServiceImpl.setCache.error:key={}, msg={}", key, e.getMessage());
        }
    }

    private String serializeKey(Object obj) {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            log.warn("AdminFriendLinkDomainServiceImpl.serializeKey.error:{}", e.getMessage());
            return String.valueOf(obj);
        }
    }
}
